package downstream

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/status"
	"mall/api/member"
	"mall/internal/conf"
	"mall/internal/constant"
	"mall/pkg/ecode"
	"mall/pkg/log"
	"mall/pkg/network"
	"mall/pkg/request_key"
	"time"
)

func newMemberClient(ctx context.Context, addr string) (
	client member.MemberClient, err error) {
	var conn *grpc.ClientConn
	conn, err = grpc.Dial(addr, grpc.WithInsecure(),
		grpc.WithUnaryInterceptor(network.ClientInterceptor(
			"bmember", time.Second*3, memberErrorTranslator)))
	if err != nil {
		err = ecode.AppendMessage(constant.ErrRemoteError, "会员服务地址无法建立有效连接, err=%s", err.Error())
		log.FromContext(ctx).Warnw(err.Error())
		return
	}
	client = member.NewMemberClient(conn)
	return
}

func memberErrorTranslator(err error) (errCode *ecode.ErrorCode) {
	rpcStatus := status.Convert(err)
	errCode = ecode.AppendMessage(
		constant.ErrRemoteError, "会员服务调用失败，请稍后再试：%s", rpcStatus.Message())
	return
}

func (d *Downstream) QueryMemberIDs(ctx context.Context, memberId uint64, sgId uint32) (
	memberIds []int64, err error) {
	if d.memberClient == nil {
		if d.memberClient, err = newMemberClient(
			ctx, conf.Conf.Downstream.MemberAddress); err != nil {
			return
		}
	}
	var resp *member.GetRelatedMemberIdsReply
	clientCtx, cancel := request_key.NewOutGoingContext(ctx, time.Second*3)
	defer cancel()
	if resp, err = d.memberClient.GetRelatedMemberIds(clientCtx, &member.GetRelatedMemberIdsReq{
		BrandId:  int64(sgId),
		MemberId: int64(memberId),
	}); err != nil {
		return
	}
	memberIds = resp.MemberIds
	return
}

func (d *Downstream) SearchMemberByKeywords(ctx context.Context,
	mobile, contact string, sgId uint32) (
	memberIds []int64, memberMap map[uint64]string, err error) {
	if d.memberClient == nil {
		if d.memberClient, err = newMemberClient(
			ctx, conf.Conf.Downstream.MemberAddress); err != nil {
			return
		}
	}
	var resp *member.MemberMobileNicknameListReply
	clientCtx, cancel := request_key.NewOutGoingContext(ctx, time.Second*3)
	defer cancel()
	if resp, err = d.memberClient.SearchMembersMobileNickname(
		clientCtx, &member.MemberMobileNicknameSearchReq{
			BrandId:  int64(sgId),
			Mobile:   mobile,
			Nickname: contact,
		}); err != nil {
		return
	}
	memberIds = make([]int64, len(resp.Members))
	memberMap = make(map[uint64]string)
	for i, m := range resp.Members {
		memberIds[i] = m.MemberId
		memberMap[uint64(m.MemberId)] = fmt.Sprintf("%s/%s", m.Nickname, m.Mobile)
	}
	return
}

// CallMemberQuery 调用会员查询
func (d *Downstream) QueryMembers(ctx context.Context, memberIDs []int64) (
	memberMap map[uint64]string, err error) {
	if d.memberClient == nil {
		if d.memberClient, err = newMemberClient(ctx, conf.Conf.Downstream.MemberAddress); err != nil {
			return
		}
	}
	var resp *member.MemberMobileNicknameListReply
	clientCtx, cancel := request_key.NewOutGoingContext(ctx, time.Second*3)
	defer cancel()
	if resp, err = d.memberClient.GetMembersMobileNickname(
		clientCtx, &member.MemberMobileNicknameGetReq{
			MemberIds: memberIDs,
		}); err != nil {
		return
	}
	memberMap = make(map[uint64]string)
	for _, m := range resp.Members {
		memberMap[uint64(m.MemberId)] = fmt.Sprintf("%s/%s", m.Nickname, m.Mobile)
	}
	return
}
